package com.wps.synergy.rpc
{
	import com.adobe.serialization.json.JSON;
	import com.wps.synergy.rpc.events.ExitEvent;
	import com.wps.synergy.rpc.events.JoinEvent;
	import com.wps.synergy.rpc.events.OperationEvent;
	import com.wps.synergy.rpc.events.ShareEvent;
	import com.wps.text.shared.cooperative.IAtomOperation;
	import com.wps.text.shared.cooperative.ICompoundOperation;
	
	import flash.events.Event;
	import flash.events.IEventDispatcher;
	import flash.net.URLLoader;
	import flash.net.URLLoaderDataFormat;
	import flash.net.URLRequest;
	import flash.net.URLRequestMethod;
	import flash.net.URLVariables;
	import flash.utils.Dictionary;
	
	import mx.rpc.http.Operation;
	
	public class Proxy implements ISynergy
	{
		public function Proxy(kliveToken:String, fileId:String, dispatcher: IEventDispatcher)
		{
			this._kliveToken = kliveToken;
			this._fileId = fileId;
			this._dispatcher = dispatcher;
			
			this.bind();
		}
		
		public function shareTo(fileId:String, sharers:Array, writable:Boolean):void
		{
			
		}
		
		public function join():void
		{
			var param:URLVariables = new URLVariables();
			param.fileHash = this._fileId;
			param.token = this._kliveToken;
			this.send(param, "join");
		}
		
		public function kick(userId:String):void
		{
			var param:URLVariables = new URLVariables();
			param.filePath = this._fileId;
			param.sid = this._sessionId;
			this.send(param, "kick");
		}
		
		public function exit():void
		{
			var param:URLVariables = new URLVariables();
			param.filePath = this._fileId;
			param.sid = this._sessionId;
			this.send(param, "exit");
		}
		
		public function saved(stateVec:Dictionary):void
		{
			var param:URLVariables = new URLVariables();
			param.filePath = this._fileId;
			param.sid = this._sessionId;
			param.vec = stateVec;
			this.send(param, "saved");
		}
		
		public function sendOperation(operation: ICompoundOperation): void
		{
			var operationObj:Object = new Object();
			var operationVecObj:Object = new Vector.<Dictionary>();
			for each (var atomOperation:IAtomOperation in operation.operationVec)
			{
				var atomOperationObj:Object = new Object();
				atomOperationObj.opType = atomOperation.opType;
				atomOperationObj.content = atomOperation.content;
				
				var pathObj:Object = new Object;
				pathObj.start = atomOperation.opPath.start;
				pathObj.end = atomOperation.opPath.end;
				pathObj.finish = atomOperation.opPath.finish;
				atomOperationObj.opPath = pathObj;
				
				operationVecObj.push(atomOperationObj);
			}
			operationObj.operationVec = operationVecObj;
			operationObj.stateVec = operation.stateVec;
			
			var param:URLVariables = new URLVariables();
			param.filePath = this._fileId;
			param.sid = this._sessionId;
			param.operation = JSON.encode(operationObj);
			this.send(param, "operation")
		}
		
		private function bind():void
		{
			this.send(new URLVariables, "bind");
		}
		
		private function send(param:URLVariables, apiName:String):void
		{
			var host:String = "";
			var apiPath:String = "";
			var url:String = host + apiPath;
			var request:URLRequest = new URLRequest(url);
			request.method = URLRequestMethod.POST;
			request.data = param;
			var loader:URLLoader = new URLLoader();
			loader.dataFormat = URLLoaderDataFormat.TEXT;
			loader.data = request;
			loader.addEventListener(Event.COMPLETE, function(event:Event):void{
				this.sendCallback(apiName, event);
			});
			loader.load(request);
		}
		
		private function sendCallback(type:String, event:Event):void
		{
			if (type == "bind")
			{
				this.bind();
			}
			
			var response:String = event.target.data as String;
			var obj:Object = JSON.decode(response);
			obj.type = type;
			this.dispatchEvent(obj);
		}
		
		private function dispatchEvent(response:Object):void
		{
			var event:Event = null;
			switch (response["type"])
			{
				case "shareTo":
					break;
				case "join":
					event = new JoinEvent(JoinEvent.JOIN_SELF, response.no, new Vector.<int>(response.v));
					this._sessionId = response.sid;
					break;
				case "kick":
					break;
				case "exit":
					event = new ExitEvent(ExitEvent.EXIT_SELF)
					break;
				case "login":
					event = new JoinEvent(JoinEvent.JOIN_OTHER, response.no);
					break;
				case "logout":
					event = new ExitEvent(ExitEvent.EXIT_OTHER, response.id);
					break;
				case "saved":
					break;
				case "operation":
					event = new OperationEvent(OperationEvent.NEW_OPERATION, null);
					break;
				default:
					break;
			}
			this._dispatcher.dispatchEvent(event);
		}
		
		private var _kliveToken:String;
		private var _fileId:String;
		private var _dispatcher:IEventDispatcher;
		
		private var _sessionId:String = null;
	}
}